//
// Created by Administrator on 2021/1/7.
//


#include <malloc.h>
#include <cstdlib>
#include <cstring>
#include <pthread.h>
#include "EnjoyPlayer.h"
#include "log.h"
extern "C"{
    #include <libavformat/avformat.h>
}



//因为此函数不属于EnjoyPlayer的函数,所以不能直接访问类中变量,此处设置为友元函数
void * prepare_t(void* arg){
    EnjoyPlayer *enjoyPlayer = static_cast<EnjoyPlayer *>(arg);
    enjoyPlayer->~prepare();
    return 0;
}

EnjoyPlayer::EnjoyPlayer(JavaCallHelp *javaCallHelp) {
    mJavaCallHelp =javaCallHelp;
}

void EnjoyPlayer::setDataSource(const char *path) {
    //因为传入进来的是指针,如果外部传进来的指针指向的内存被释放了,那么就会导致类中的mPath指向的空间也释放
    //mPath = path;
    //所以本地拷贝一份
    //mPath = static_cast<const char *>(malloc(strlen(path) + 1));
    mPath = new char[strlen(path) + 1];
    //进行复制
    strcpy(mPath,path);
}

void EnjoyPlayer::prepare(){
    //因为是耗时操作,那么就创建c层的线程
   pthread_create(&pthread, NULL,prepare_t,this);

}
void EnjoyPlayer::~prepare(){
    //初始化AVFormatContext环境
    AVFormatContext *avFormatContext =avformat_alloc_context();

    //参数3： 输入文件的封装格式 ，传null表示 自动检测格式。 avi / flv
    //参数4： map集合，比如打开网络文件，
    AVDictionary *opts;
    av_dict_set(&opts,"timeout","3000000",0);
    int result = avformat_open_input(&avFormatContext,mPath,0,&opts);
    if(result!=0){//0表示成功
        //打印log,并且通知上层,出错了
        LOGE("打开%s 失败，返回:%d 错误描述:%s", mPath, result, av_err2str(result));
        mJavaCallHelp->onError(result,2);
        return ;
    }

    /*
     * 查找媒体流
     * */
    int ret =avformat_find_stream_info(avFormatContext,0);
    if(ret<0){
        //打印log,并且通知上层,出错了
        LOGE("查找媒体流%s 失败，返回:%d 错误描述:%s", mPath, result, av_err2str(result));
        mJavaCallHelp->onError(result,2);
        return ;
    }

    //得到视频的时长,单位为秒
    long duration =avFormatContext->duration/AV_TIME_BASE;
    LOGE("视频时长:%l", duration);

    //查看有几道媒体流,通过for循环得到所有的流,此处有视频流和音频流,
    for (int i = 0; i <avFormatContext->nb_streams ; ++i) {
      AVStream *avStream =  avFormatContext->streams[0];
      //获得解码信息
      AVCodecParameters avCodecParameters =avStream->codecpar;

      //查找解码器
      AVCodec *dec = avcodec_find_decoder(avCodecParameters.codec_id);
      if(!dec){//如果没办法解码
          LOGE("查找解码器失败");
        mJavaCallHelp->onError(FFMPEG_FIND_DECODER_FAIL,THREAD_CHILD);
          return;
      }

      AVCodecContext *codecContext = avcodec_alloc_context3(dec);
      //把解码信息数据
        // 把解码信息赋值给了解码上下文中的各种成员
        if (avcodec_parameters_to_context(codecContext, &avCodecParameters) < 0) {
            mJavaCallHelp->onError(FFMPEG_CODEC_CONTEXT_PARAMETERS_FAIL, THREAD_CHILD);
            return;
        }
        // 打开解码器
        if (avcodec_open2(codecContext, dec, 0) != 0) {
            //打开失败
            mJavaCallHelp->onError(FFMPEG_OPEN_DECODER_FAIL, THREAD_CHILD);
            return;
        }


        if (avCodecParameters.codec_type == AVMEDIA_TYPE_AUDIO) {

        } else if (avCodecParameters.codec_type == AVMEDIA_TYPE_VIDEO) {
            // 帧率
            int fps = av_q2d(avStream->avg_frame_rate);

            //videoChannel = new VideoChannel(i, helper, codecContext, avStream->time_base, fps);
        }
    }


}
